package homework.server;

import sun.nio.cs.StreamDecoder;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;

public class IOStream implements Closeable {

    private Socket socket;

    private InputStream in;
    private OutputStream out;

    private Charset charset;
    private StreamDecoder decoder;

    public IOStream() {
        this(Charset.defaultCharset());
    }

    public IOStream(Charset charset) {
        this(System.in, System.out, charset);
    }

    public IOStream(Socket socket) throws IOException {
        this(socket, Charset.defaultCharset());
    }

    public IOStream(Socket socket, Charset charset) throws IOException {
        this(socket.getInputStream(), socket.getOutputStream(), charset);
        this.socket = socket;
    }

    public IOStream(InputStream in, OutputStream out) {
        this(in, out, Charset.defaultCharset());
    }

    public IOStream(InputStream in, OutputStream out, Charset charset) {
        this.in = in;
        this.out = out;
        this.charset = charset;
    }

    public InputStream getInputStream() {
        return in;
    }

    public OutputStream getOutputStream() {
        return out;
    }

    public int read() throws IOException {
        return in.read();
    }

    public int read(byte[] var1) throws IOException {
        return in.read(var1);
    }

    public int read(byte[] var1, int off, int len) throws IOException {
        return in.read(var1, off, len);
    }

    public byte[] readAll() throws IOException {
        byte[] buf = new byte[in.available()];
        read(buf);
        return buf;
    }

    public void write(int var1) throws IOException {
        out.write(var1);
    }

    public void write(byte[] var1) throws IOException {
        out.write(var1);
    }

    public void write(byte[] var1, int off, int len) throws IOException {
        out.write(var1, off, len);
    }

    public void write(String str) throws IOException {
        write(str.getBytes(charset));
    }

    public void writeLine(String str) throws IOException {
        write(str+"\n");
    }

    public String readString() throws IOException {
        return readString(charset);
    }

    public String readString(Charset charset) throws IOException {
        byte[] buf = new byte[in.available()];
        read(buf);
        return new String(buf, charset);
    }

    public synchronized String readLine(Charset charset) throws IOException {
        StreamDecoder sd = StreamDecoder.forInputStreamReader(in, this, charset);
        StringBuilder builder = new StringBuilder();
        int code;
        while ((code = sd.read()) != -1 && code != 10)
            builder.append((char) code);

        builder.append('\n');
        return builder.toString();
    }

    public String readLine() throws IOException {
        return readLine(charset);
    }

    public int available() {
        try {
            return in.available();
        } catch (IOException e) {
            return -1;
        }
    }

    public boolean isSocketClosed() {
        if(socket == null) throw new UnsupportedOperationException();
        try {
            socket.sendUrgentData(0xff);
        } catch (IOException e) {
            return true;
        }
        return false;
    }

    @Override
    public void close() throws IOException {
        if(socket != null && !socket.isClosed()) socket.close();
        in.close();
        out.close();
    }

    public void setCharset(Charset charset) {
        this.charset = charset;
    }

    public void setCharset(String charsetName) {
        setCharset(Charset.forName(charsetName));
    }

    public Charset getCharset() {
        return charset;
    }

    public static void main(String[] args) throws IOException {
        IOStream stream = new IOStream();
        while (true) {
            String str = null;
            if(stream.in.available() != 0) {
                str = stream.readString(Charset.forName("utf-8"));
                System.out.println("'"+str+"'");
            }
            if(str != null && str.startsWith("quit")) {
                break;
            }
        }
    }
}
